// X10.java

package com.ibm.tspaces.examples.x10;


// OEM Certified:  jthomas, Jan 30, 1999
/*
**  Licensed Materials - Property of IBM
**
**  (C) COPYRIGHT IBM Corp. 1996, 1997  All rights reserved
**
**  US Government Users Restricted Rights - Use, duplication or
**  disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
*/

import com.ibm.tspaces.*;

import java.io.*;
import java.util.*;
import javax.comm.*;

/**
** X10 is a utility class that contains constants and 
** common utility function for the X10 support
**<p>
** Overview of the TSpace - X10 support classes
**<ul>
** <li>X10Monitor.java -  This class provides the basic support for the 
**     X10 comm port.  When important X10 events occur 
**     (i.e. A light On command is issued) then this is translated into
**     a java event (X10Event)
** 
** <li>X10Event.java - Extends EventObject and defines the basic X10 events
**
** <li>X10EventListner - efines the X10EventListner Interface which consists 
**       currently of one method "functionPerformed()"
**
** <li>TSX10.java - This implements the main X10 - TSpaces process. 
**   when invoked (main() method), it will setup one or more X10Monitor tasks
**   that will interface to the X10 communication post.  It will register to 
**   listen for X10Event actions and implements X10EventListener.  
** 
** <li>X10Device.java - Implements the basic functiolity of an X10 device.
**  
** <li>X10Lamp.java - subclasses X10Device to define an X10 Lamp device
**       ( Adds dim and bright functions)
** 
** <li>X10Queue.java - Utility class to handle event queueing
**
** <li>X10MonitorException.java - Define X10Monitor exceptions
**
** <li>X10View.java - Implements a simple applet to display X10 status.
** 
** <li>X10ViewPanel.java - Used by X10View 
** <li>X10DevicePanel.java - Used by X10View
**
** </ul>
**
** @see X10Monitor
** @see X10Device
** @see TSX10
**
** @author  John Thomas
** @version     $Revision: 2.1 $ $Date: 1999/11/05 22:22:40 $
*/
public class X10  {

	
	
	
/**
** Interface Poll ack
*/
static final byte[]  _POLL_ACK = {(byte)0xC3};

/**
** Poll Request from interface to the PC
*/
static final byte    _POLL_REQ = 0x5A;

/**
** Ready Request from interface to the PC
*/

static final byte    _READY_REQ =0x55;

/**
** TimeRequest from CM11 interface
*/
static final byte    _CM11_TIME_REQ =(byte)0xA5;
/**
** TimeRequest from CP10 interface
*/
static final byte    _CP10_TIME_REQ =0x6B;
	
/**
** Function Codes
*/
static final int _ALL_UNITS_OFF  = 0;
static final int _ALL_LIGHTS_ON  = 1;	
static final int _ON             = 2;
static final int _OFF            = 3;
static final int _DIM            = 4;
static final int _BRIGHT         = 5;
static final int _ALL_LIGHTS_OFF = 6;
static final int _EXTENDED_CODE  = 7;
static final int _HAIL_REQUEST   = 8;
static final int _HAIL_ACK       = 9;
static final int _PRESET_DIM_1   = 10;
static final int _PRESET_DIM_2   = 11;
static final int _EXTENDED_DATA  = 12;
static final int _STATUS_ON      = 13;
static final int _STATUS_OFF     = 14;
static final int _STATUS_REQUEST = 15;
	
	
/**
** Table of Hex values used to display info in Hex format
**   System.out.println("value="+HEXTABLE[value]);
*/
  static String[] HEXTABLE = new String[256];
/** 
** static initializer to fill in the HEXTABLE
*/
  static {
    char c1;
    char c2;
    for (int i=0; i< 16; i++) {
      if (i < 10) 
        c1 = (char)('0'+i);
      else 
        c1 = (char)('A'+(i-10));
      for (int j=0;j<10;j++) {
        c2 = (char)('0'+j);        
        HEXTABLE[i*16+j] = ""+c1+c2;
      }
      for (int j=10;j<16;j++) {
        c2 = (char)('A'+(j-10));        
        HEXTABLE[i*16+j] = ""+c1+c2;
      }

    }
  }
	
	/***********************************************************
  ** Hex **
  *********/ 
  /**
  ** static method to return the Hex value of a byte value
  ** This method will take a byte value and return the 
  ** equivalent string.
  ** <pre>
  **   byte b = 255;
  **   String x = Hex(b); -> x'FF'
  **
  ** @param value The byte value. 
  ** @returns The hex representation as a 2 character string.
  */
  static String 
  Hex(byte value) {
  	int ib = (int)value;
    return Hex(ib);
  }
  
	/***********************************************************
  ** Hex **
  *********/ 
  /**
  ** static method to return the Hex value of a byte array
  ** This method will take an array of  bytes and return the 
  ** equivalent string.
  ** <pre>
  **   byte[] bytes = { 1,2,3 };
  **   String x = Hex(b); -> x'01'x'02'x'03'
  **
  ** @param value The byte array
  ** @returns The hex representation as a string.
  */

	static String 
	Hex(byte[] array) {
		if (array == null) 
			return "null";
		StringBuffer sb = new StringBuffer(array.length*5);
		for (int i=0;i<array.length;i++) {
			sb.append(Hex(array[i]));
		}
		return sb.toString();
	}
	

	
	/**
  ** static method to return the Hex value of an int.
  ** This method will take a byte value and return the 
  ** equivalent string.
  ** <pre>
  **   int i = 255;
  **   String x = Hex(i); -> x'FF'
  **
  ** @param value The integer value. 
  ** @returns The hex representation as a 2 character string.
  ** If it is outside the range of 0 to 255, then it will be
  ** truncated to that range  I.e. 256 -> 0 
  */

  static String 
  Hex(int value) { 
  	
    if (value >= 256 || value <0 ) 
      value = value%256;  
  	if (value < 0 ) 
      value = value + 256;
    return "x'"+HEXTABLE[value]+"'";
  }

  /**
  ** Used to convert binary value to HouseCode
  */
	static final String[] HOUSE_CODES = { 
		     "M","C","E","K", 
		     "O","G","A","I",
		     "N","F","D","L",
		     "P","H","B","J"  };
	/**
  ** Used to convert binary value to DeviceCode
  */
  static final int[] DEVICE_CODES = { 
         13,5,3,11,
         15,7,1,9,
         14,6,4,12,
         16,8,2,10 };
  /**
  ** Used to convert DeviceCode or HousCode to binary value 
  */
  static final int[] BINARY_CODES = { 
         6,14,2,10,
         1,9,5,13,
         7,15,3,11,
         0,8,4,12 };

	/**
  ** Used to convert FuntionCode to String 
  */
  static final String[] FUNCTION_NAMES = { 
         "All units Off",
         "All Lights On",
         "On",
         "Off",
         "Dim",
         "Bright",
         "All Lights Off",
         "Extended Code",
         "Hail Request",
         "Hail Acknowledge",
         "Pre-set Dim 1",
         "Pre-set Dim 2",
         "Extended Data Transfer",
         "Status On",
         "Status Off",
         "Status Request" };

	
  /***********************************************************
  ** bin2Code **
  *****************/ 
  /**
  ** static method to convert an 8 bit value into 
  ** an X10 addres. 
  ** For Example: 
  **   x'6E' -> "A2"  
  **
  ** @param value The byte value. 
  ** @returns The Device address.
  */
  static String 
  bin2Code(byte value) {
  	int hValue = ((int)value)>>4;
  	int dValue = value & 0x0f; 
    
    return HOUSE_CODES[hValue]+DEVICE_CODES[dValue];
  }
  
  /***********************************************************
  ** code2Bin *
  *****************/ 
  /**
  ** static method to convert an an X10 address as a String
  ** to a binary address.
  ** For Example: 
  **   "A2"  -> 0x62  
  **
  ** @param value The device address as a String
  ** @returns The Device address.as a binary integer
  */
  static byte
  code2Bin(String address) throws X10MonitorException {
  	try {
  	  int hCode = (int)address.charAt(0);
  		hCode = hCode - 'A';
    	int dCode = Integer.parseInt(address.substring(1)) - 1;
  		if (dCode < 0 || dCode > 15 || hCode <0 || hCode > 15)
  			throw new X10MonitorException("Invalid address "+address);
    	int result = BINARY_CODES[hCode]*16 + BINARY_CODES[dCode];
  		return (byte)result;
  	} catch (Exception e) {
  		throw new X10MonitorException("Invalid address "+address);
  	}
  }
  /***********************************************************
  ** calcCheckSum *
  *****************/ 
  /**
  ** static method to calculate the 
  ** expected checksum tht the PC interface will 
  ** return to an address or function
  **
  ** @param value The bytes sent to the interface
  ** @returns The expected Checksum
  */
  static byte
  calcCheckSum(byte[] bytes) {
  	byte expectedCheckSum = 0;
    for (int i=0; i<bytes.length;i++) 
        expectedCheckSum += bytes[i];
    expectedCheckSum = (byte)(expectedCheckSum & 0xff);
  	return expectedCheckSum;
  }

/***********************************************************
  ** delay **
  ******************************/
  /**
  ** A convienent way to delay for n seconds  
  */

 
  
  static void
  delay(int seconds) {
    
    try {
      Thread.sleep(seconds*1000);
    } catch (InterruptedException e) {
      
    }
  }
  
	
	/***********************************************************
  ** main **
  ******************************/
  /**
  ** main() method to do a simple unit test of the X10 class
  ** 
  ** Normally the X10 class would be instantiated by 
  ** an external application.
  */
  
  public static void 
  main (String[] args) {
      
    
    Debug.setDebugOn(true);  
    

    try {
    
    	byte b = 0x2f;
    	Debug.out("0x22f="+Hex(b));
    	
    	byte[] bytes = {(byte)0x00,(byte)0xff};
    	Debug.out("{0x00,0xff}="+Hex(bytes));
    
    } catch (Exception e) {
      Debug.out(e);
    }
    Debug.out("main() ending.");	
  	
   
  }
  
} // X10
/* $Log: X10.java,v $
/* Revision 2.1  1999/11/05 22:22:40  estesp
/* Update revision number to 2.1 on all files
/*
/* Revision 1.1.1.1  1999/11/05 16:24:53  estesp
/* Imported 2.1.0 release into Austin CVS
/*
 * Revision 1.2  1999/06/17 05:39:48  thodes
 *   Updated the inital checkin to append the "Log" field and
 * convert CR/LF to CR (for win/unix interop).
 *
 *   The inital checkin lower-cased directrory names, and omitted
 * many dirs/files that will added later, e.g., MoDAL stuff.
 *
 * All of the above will need to be done to all VSS-to-CVS
 * converted sources.  In summary, in moving from VSS to CVS, do this:
 *  - lower-case dir names
 *  - CR/LF --> CR
 *  - append CVS "Log" entties
 *
 * (a script that helps with #2 and #3 is in
 *     tspaces1:~thodes/bin/update-keywords.sh)
 * 
 */


